package service

import (
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"

	"yanxue_ai_go/pkg/common/database"
)

// AuthService 认证服务
type AuthService struct {
	jwtSecret []byte
}

// User 用户模型
type User struct {
	ID           uint      `json:"id" gorm:"primarykey"`
	Username     string    `json:"username" gorm:"uniqueIndex;not null"`
	Email        string    `json:"email" gorm:"uniqueIndex;not null"`
	PasswordHash string    `json:"-" gorm:"not null"`
	Role         string    `json:"role" gorm:"default:user"`
	Status       string    `json:"status" gorm:"default:active"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

// NewAuthService 创建认证服务
func NewAuthService() *AuthService {
	return &AuthService{
		jwtSecret: []byte("your-jwt-secret-key"), // 应该从配置中读取
	}
}

// Register 用户注册
func (as *AuthService) Register(username, email, password string) error {
	// 检查用户是否已存在
	var existingUser User
	if err := database.DB.Where("username = ? OR email = ?", username, email).First(&existingUser).Error; err == nil {
		return errors.New("user already exists")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// 创建用户
	user := User{
		Username:     username,
		Email:        email,
		PasswordHash: string(hashedPassword),
		Role:         "user",
		Status:       "active",
	}

	return database.DB.Create(&user).Error
}

// Login 用户登录
func (as *AuthService) Login(username, password string) (string, error) {
	var user User
	if err := database.DB.Where("username = ? OR email = ?", username, username).First(&user).Error; err != nil {
		return "", errors.New("user not found")
	}

	// 验证密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil {
		return "", errors.New("invalid password")
	}

	// 生成JWT令牌
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id":  user.ID,
		"username": user.Username,
		"role":     user.Role,
		"exp":      time.Now().Add(time.Hour * 24).Unix(),
	})

	tokenString, err := token.SignedString(as.jwtSecret)
	if err != nil {
		return "", err
	}

	return tokenString, nil
}

// RefreshToken 刷新令牌
func (as *AuthService) RefreshToken(refreshToken string) (string, error) {
	// 验证刷新令牌
	token, err := jwt.Parse(refreshToken, func(token *jwt.Token) (interface{}, error) {
		return as.jwtSecret, nil
	})

	if err != nil || !token.Valid {
		return "", errors.New("invalid refresh token")
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok {
		return "", errors.New("invalid token claims")
	}

	// 生成新的访问令牌
	newToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id":  claims["user_id"],
		"username": claims["username"],
		"role":     claims["role"],
		"exp":      time.Now().Add(time.Hour * 24).Unix(),
	})

	return newToken.SignedString(as.jwtSecret)
}

// RevokeToken 撤销令牌
func (as *AuthService) RevokeToken(token string) error {
	// 在实际实现中，应该将令牌加入黑名单
	// 这里只是示例实现
	return nil
}

// ValidateToken 验证令牌
func (as *AuthService) ValidateToken(tokenString string) (*jwt.MapClaims, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return as.jwtSecret, nil
	})

	if err != nil || !token.Valid {
		return nil, errors.New("invalid token")
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok {
		return nil, errors.New("invalid token claims")
	}

	return &claims, nil
}
